module players
	use pieces
    implicit none
    private
    public player_module_initialize, player_module_finalize
    public player
    public new, destroy, as_string, holdings, give, take
    public number_of_wins, record_win, controller, set_controller

    integer, public, parameter:: ai_controller = 1
    integer, public, parameter:: human_controller = 2

    integer, parameter:: player_name_size = 1

    type player
      private
      character(len=player_name_size):: name = " "
      integer:: number_of_wins = 0
	  type(piece), pointer:: holdings(:) => Null()
	  integer:: number_of_pieces = 0
      integer:: controller = ai_controller
    end type player

    interface as_string
        module procedure player_as_string
    end interface

    interface new
        module procedure player_new
    end interface

    interface destroy
        module procedure player_destroy
    end interface

	interface take            ! take a piece from the player
		module procedure player_take
	end interface take

	interface give
		module procedure player_give
	end interface give

	interface controller
		module procedure player_controller
	end interface controller

	interface set_controller
		module procedure player_set_controller
	end interface set_controller

	interface holdings
		module procedure player_pieces
	end interface holdings

contains

    subroutine player_module_finalize ()
    end subroutine player_module_finalize

    subroutine player_module_initialize ()
    end subroutine player_module_initialize

    pure function player_as_string(p)
    character player_as_string
    type(player), intent(in):: p
    player_as_string = p%name
    end function player_as_string

    integer function number_of_wins(p)
    type(player), intent(in):: p
    number_of_wins = p%number_of_wins
    end function number_of_wins

    subroutine record_win(p)
    type(player), intent(inout):: p
    p%number_of_wins = p%number_of_wins + 1
    end subroutine record_win

	function player_pieces(p) 
	type(player), intent(in)::p
	type(piece), pointer:: player_pieces(:)
	player_pieces => p%holdings
	end function player_pieces

	function player_controller(p) 
	type(player), intent(in)::p
	integer player_controller
	player_controller = p%controller
	end function player_controller

	subroutine player_set_controller(p, c) 
	type(player), intent(inout)::p
	integer c
    select case(c)
    case (ai_controller, human_controller)
	    p%controller = c
    case default
        stop "Improper controller requested."
    end select
	end subroutine player_set_controller

    subroutine player_new (new_player, name)
    character*(*) name
    type(player),intent(out):: new_player
    new_player%name = name
    new_player%number_of_wins = 0
	allocate(new_player%holdings(1))
    end subroutine player_new

    subroutine player_destroy(dying_player)
    type(player),intent(inout):: dying_player
	deallocate(dying_player%holdings)
    end subroutine player_destroy

	function player_give(p, a_piece)
	type(player), intent(inout):: p
	type(piece), intent(in):: a_piece
	type(piece), pointer:: new_pieces(:)
	type(piece), pointer:: old_pieces(:)
	integer player_give

	p%number_of_pieces = p%number_of_pieces + 1
	if (size(p%holdings) < p%number_of_pieces) then
		old_pieces => p%holdings
		allocate(new_pieces(p%number_of_pieces))
		p%holdings => new_pieces
		p%holdings(1:p%number_of_pieces - 1) = old_pieces
		deallocate(old_pieces)
	endif
	p%holdings(p%number_of_pieces) = a_piece
	player_give = p%number_of_pieces
	end function player_give

	subroutine player_take(p, n) 
	type(player), intent(inout)::p
	integer, intent(in):: n
	integer m

	m = p%number_of_pieces
	p%holdings(n:m-1) = p%holdings(n+1:m)
	p%number_of_pieces = m - 1
	end subroutine player_take

end module players